<template>
  <div style="padding: 32px;">
    <div style="font-size: 24px; font-weight: bold; text-align: center; margin-bottom: 24px;">
      角色权限分配
    </div>
    <v-row>
      <v-col cols="12" md="4">
        <v-card elevation="2" class="mb-4">
          <v-card-title>角色列表</v-card-title>
          <v-list>
            <v-list-item v-for="role in roles" :key="role.id" :active="role.id === selectedRoleId" @click="selectRole(role.id)">
              <v-list-item-title>{{ role.name }}</v-list-item-title>
              <v-list-item-subtitle>{{ role.code }}</v-list-item-subtitle>
            </v-list-item>
          </v-list>
        </v-card>
      </v-col>
      <v-col cols="12" md="8">
        <v-card elevation="2">
          <v-card-title>
            <div class="d-flex align-center justify-space-between w-100">
              <div>
                <span style="font-weight:600;font-size:18px;">当前角色：</span>
                <span v-if="currentRole" style="font-weight:bold;font-size:18px;">{{ currentRole.name }}</span>
                <span v-if="currentRole" style="color:#888;font-size:14px;margin-left:8px;">({{ currentRole.code }})</span>
                <span v-else style="color:#aaa;font-size:16px;">未选择角色</span>
              </div>
            </div>
          </v-card-title>
          <v-card-text>
            <v-skeleton-loader v-if="rightLoading" type="card, list-item, list-item, list-item, list-item" :loading="rightLoading" />
            <template v-else>
              <v-form @submit.prevent="onSaveResource" ref="formRef">
                <v-row>
                  <v-col cols="12" sm="6">
                    <v-text-field v-model="resourceForm.resourceName" label="权限名称" required />
                  </v-col>
                  <v-col cols="12" sm="6">
                    <v-text-field
                      v-model="resourceForm.url"
                      label="URL"
                      required
                      prepend-inner="/actions"
                      :formatter="urlFormatter"
                      :parse-input="urlParser"
                    />
                  </v-col>
                  <v-col cols="12" sm="6">
                    <v-select v-model="resourceForm.method" :items="['GET', 'POST']" label="请求方式" required />
                  </v-col>
                  <v-col cols="12" sm="6">
                    <v-text-field v-model="resourceForm.description" label="描述" />
                  </v-col>
                </v-row>
                <v-btn color="primary" type="submit" :loading="loading">新增权限</v-btn>
              </v-form>
              <div style="margin-top:32px;">
                <div style="font-size:18px;font-weight:600;margin-bottom:8px;">当前角色拥有的权限</div>
                <div v-for="(group, prefix) in groupedRoleResources" :key="prefix" style="margin-bottom: 18px;">
                  <div style="font-size:15px;font-weight:600;color:#1976d2;margin-bottom:4px;">
                    <v-icon size="16" style="vertical-align:middle;">mdi-folder</v-icon>
                    <span style="vertical-align:middle;">{{ prefix }}</span>
                  </div>
                  <v-list density="compact">
                    <v-list-item v-for="res in group" :key="res.resourceId">
                      <v-list-item-title>{{ res.resource_name }}</v-list-item-title>
                      <v-list-item-subtitle>{{ res.method }} {{ res.url }}</v-list-item-subtitle>
                    </v-list-item>
                  </v-list>
                </div>
                <div v-if="Object.keys(groupedRoleResources).length === 0">
                  <v-list density="compact">
                    <v-list-item>
                      <v-list-item-title style="color:#aaa;">暂无权限</v-list-item-title>
                    </v-list-item>
                  </v-list>
                </div>
              </div>
              <div style="margin-top:32px;">
                <div style="font-size:18px;font-weight:600;margin-bottom:8px;">全部权限分配</div>
                <v-btn color="primary" class="mt-2" @click="showAssignDialog = true">批量分配权限</v-btn>
              </div>
              <v-snackbar v-model="allocateSuccess" color="success" timeout="2000">分配成功</v-snackbar>
              <v-dialog v-model="showDetailDialog" max-width="500px">
                <v-card>
                  <v-card-title>权限详情</v-card-title>
                  <v-card-text>
                    <div v-if="detailResource">
                      <div><b>权限名称：</b>{{ detailResource.resource_name }}</div>
                      <div><b>URL：</b>{{ detailResource.url }}</div>
                      <div><b>请求方式：</b>{{ detailResource.method }}</div>
                      <div><b>描述：</b>{{ detailResource.description }}</div>
                    </div>
                  </v-card-text>
                  <v-card-actions>
                    <v-spacer />
                    <v-btn text @click="showDetailDialog = false">关闭</v-btn>
                  </v-card-actions>
                </v-card>
              </v-dialog>
              <!-- 权限分配弹窗 -->
              <v-dialog v-model="showAssignDialog" max-width="700px">
                <v-card>
                  <v-card-title>批量分配权限</v-card-title>
                  <v-card-text style="max-height:60vh;overflow:auto;">
                    <v-expansion-panels multiple>
                      <v-expansion-panel v-for="(group, prefix) in groupedAllResources" :key="prefix">
                        <v-expansion-panel-title>
                          <v-icon size="16" style="vertical-align:middle;">mdi-folder</v-icon>
                          <span style="vertical-align:middle;margin-left:4px;">{{ prefixNameMap[prefix] || prefix }}</span>
                        </v-expansion-panel-title>
                        <v-expansion-panel-text>
                          <v-list density="compact">
                            <v-list-item v-for="res in group" :key="res.resourceId" class="assign-list-item" style="padding-left:0;padding-right:0;">
                              <div class="assign-flex-row">
                                <v-checkbox v-model="checkedResourceIds" :value="res.resourceId" hide-details class="mr-2" style="margin:0;" />
                                <span class="resource-name-link" @click="showResourceDetail(res)">{{ res.resource_name }}</span>
                                <v-spacer />
                                <v-btn icon size="small" color="error" class="ml-2" @click="confirmDelete(res)"><v-icon>mdi-delete</v-icon></v-btn>
                              </div>
                            </v-list-item>
                          </v-list>
                        </v-expansion-panel-text>
                      </v-expansion-panel>
                    </v-expansion-panels>
                    <div v-if="Object.keys(groupedAllResources).length === 0">
                      <v-list density="compact">
                        <v-list-item>
                          <v-list-item-title style="color:#aaa;">暂无权限</v-list-item-title>
                        </v-list-item>
                      </v-list>
                    </div>
                  </v-card-text>
                  <v-card-actions>
                    <v-spacer />
                    <v-btn text @click="showAssignDialog = false">取消</v-btn>
                    <v-btn color="primary" @click="handleAllocate" :disabled="!checkedResourceIds.length">批量分配权限</v-btn>
                  </v-card-actions>
                </v-card>
              </v-dialog>
            </template>
          </v-card-text>
        </v-card>
      </v-col>
    </v-row>
    <v-dialog v-model="showDeleteDialog" max-width="350px">
      <v-card>
        <v-card-title>确认删除</v-card-title>
        <v-card-text>确定要删除该权限吗？此操作不可恢复。</v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn text @click="showDeleteDialog = false">取消</v-btn>
          <v-btn color="error" @click="handleDeleteResource">删除</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, computed } from 'vue'
import { getResourceList, saveOrUpdateResource, getResourceListByRole, assignResourceToRole, deleteResource } from '@/api/resource'
import axios from 'axios'
import { API_BASE_URL } from '@/config/api'

const roles = ref([])
const selectedRoleId = ref(null)
const resourceForm = ref({
  resourceName: '',
  url: '/actions',
  method: '',
  description: ''
})
const loading = ref(false)
const formRef = ref(null)
const roleResources = ref([])
const allResources = ref([])
const checkedResourceIds = ref([])
const allocateSuccess = ref(false)
const showDetailDialog = ref(false)
const detailResource = ref(null)
const showDeleteDialog = ref(false)
const deleteResourceId = ref(null)
const rightLoading = ref(false)
const showAssignDialog = ref(false)

// 权限分组映射及顺序
const prefixNameMap = {
  resourceManage: '资源管理',
  notice: '公告管理',
  role: '角色管理',
  departmentManage: '部门管理',
  userManageUrl: '用户相关',
  menuManageUrl: '菜单管理',
  其他: '其他'
}
const prefixOrder = [
  'resourceManage',
  'noticeManage',
  'roleManage',
  'departMentManage',
  'userManage',
  'menuManage',
  '其他'
]

const currentRole = computed(() => roles.value.find(r => r.id === selectedRoleId.value) || null)

// 分类分组：按url的第二个前缀分组，带映射和排序
const groupedRoleResources = computed(() => {
  const groups = {}
  for (const res of roleResources.value) {
    let prefix = '其他'
    if (res.url && res.url.startsWith('/actions/')) {
      const match = res.url.match(/^\/actions\/([^/]+)/)
      if (match && match[1]) prefix = match[1]
    }
    if (!groups[prefix]) groups[prefix] = []
    groups[prefix].push(res)
  }
  // 排序
  const ordered = {}
  for (const key of prefixOrder) {
    if (groups[key]) ordered[key] = groups[key]
  }
  // 追加未在顺序表中的分组
  for (const key in groups) {
    if (!ordered[key]) ordered[key] = groups[key]
  }
  return ordered
})

const groupedAllResources = computed(() => {
  const groups = {}
  for (const res of allResources.value) {
    let prefix = '其他'
    if (res.url && res.url.startsWith('/actions/')) {
      const match = res.url.match(/^\/actions\/([^/]+)/)
      if (match && match[1]) prefix = match[1]
    }
    if (!groups[prefix]) groups[prefix] = []
    groups[prefix].push(res)
  }
  // 排序
  const ordered = {}
  for (const key of prefixOrder) {
    if (groups[key]) ordered[key] = groups[key]
  }
  for (const key in groups) {
    if (!ordered[key]) ordered[key] = groups[key]
  }
  return ordered
})

function fetchRoles() {
  const formData = new URLSearchParams()
  formData.append('pageNum', 1)
  formData.append('pageSize', 9999)
  axios.post(`${API_BASE_URL}/actions/role/list`, formData, {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
  }).then(res => {
    roles.value = res.data.list || []
    if (!selectedRoleId.value && roles.value.length) {
      selectedRoleId.value = roles.value[0].id
    }
  })
}

function selectRole(id) {
  selectedRoleId.value = id
  loadRightContent()
}

function loadRightContent() {
  rightLoading.value = true
  Promise.all([
    fetchRoleResources(selectedRoleId.value),
    fetchAllResources()
  ]).finally(() => {
    rightLoading.value = false
  })
}

function fetchRoleResources(roleId) {
  return getResourceListByRole(roleId).then(res => {
    roleResources.value = res.data.data || []
    checkedResourceIds.value = roleResources.value.map(r => String(r.resourceId || r.resource_id))
  })
}

function fetchAllResources() {
  return getResourceList({ pageNum: 1, pageSize: 9999 }).then(res => {
    allResources.value = (res.data.list || res.data.data || []).map(r => ({
      ...r,
      resourceId: String(r.resourceId || r.resource_id)
    }))
  })
}

function handleAllocate() {
  if (!selectedRoleId.value || !checkedResourceIds.value.length) return
  assignResourceToRole({
    roleId: String(selectedRoleId.value),
    resourceId: checkedResourceIds.value.join(',')
  }).then(() => {
    fetchRoleResources(selectedRoleId.value)
    allocateSuccess.value = true
    setTimeout(() => { allocateSuccess.value = false }, 2000)
    showAssignDialog.value = false
  })
}

function onSaveResource() {
  if (!resourceForm.value.resourceName || !resourceForm.value.url || !resourceForm.value.method) return
  loading.value = true
  saveOrUpdateResource({
    ...resourceForm.value,
    roleId: selectedRoleId.value
  }).then(() => {
    resourceForm.value = { resourceName: '', url: '/actions', method: '', description: '' }
    if (formRef.value) formRef.value.resetValidation()
  }).finally(() => {
    loading.value = false
  })
}

function showResourceDetail(res) {
  detailResource.value = res
  showDetailDialog.value = true
}

function confirmDelete(res) {
  deleteResourceId.value = res.resourceId
  showDeleteDialog.value = true
}

function handleDeleteResource() {
  if (!deleteResourceId.value) return
  deleteResource(deleteResourceId.value).then(() => {
    showDeleteDialog.value = false
    fetchAllResources()
    // 可选：弹出删除成功提示
  })
}

function urlFormatter(val) {
  if (!val) return ''
  return val.startsWith('/actions') ? val : '/actions' + (val.startsWith('/') ? '' : '/') + val
}

function urlParser(val) {
  if (!val) return ''
  return val.replace(/^\/actions/, '')
}

onMounted(() => {
  fetchRoles()
  loadRightContent()
})
</script>

<style scoped>
.resource-name-link {
  color: #fff;
  cursor: pointer;
  font-size: 17px;
  font-weight: 600;
  margin-left: 8px;
  text-decoration: none;
}
.resource-name-link:hover {
  color: #fff;
}
/* 权限项紧凑样式 */
.assign-list-item {
  min-height: 32px !important;
  padding-top: 2px !important;
  padding-bottom: 2px !important;
  align-items: center !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}
.assign-flex-row {
  display: flex;
  align-items: center;
  width: 100%;
}
</style>
